/*
 * UpdateDatabase.java
 *
 * Copyright(c) 2010
 * Michael Kroez
 * kroez@studiorutton.de
 *
 * All rights reserved.
 *
 * $Id$
 * 
 */

package de.studiorutton.gerengdic.update;

import java.util.ArrayList;

import android.util.Log;

import de.studiorutton.access.Result;
import de.studiorutton.access.Result.ErrorCode;
import de.studiorutton.gerengdic.R;
import de.studiorutton.gerengdic.library.LibraryDatabase;

public class UpdateDatabase {
	private static final String TAG = "learningwords";
	private static UpdateDatabase INSTANCE = null;
	
	private UpdateDatabaseAdapter uda;

	private ArrayList<UpdateFileTaskFacade> updateDatabase;
	private boolean isRunning;
	private int crrDownloadTask;
	private boolean isNewer;
	private IUpdateTaskEventListener myUtel, utel;

	public final static int DE_EN_DICT = 0;
	public final static int DE_STAT = 1;
	public final static int EN_STAT = 2;

	private UpdateDatabase() {
		updateDatabase = new ArrayList<UpdateFileTaskFacade>();
		updateDatabase.add(new UpdateFileTaskFacade(LibraryDatabase.DE_EN_DICT,
				R.string.dictionary_library_database));
		updateDatabase.add(new UpdateFileTaskFacade(LibraryDatabase.DE_STAT,
				R.string.dictionary_german_statistics));
		updateDatabase.add(new UpdateFileTaskFacade(LibraryDatabase.EN_STAT,
				R.string.dictionary_english_statistics));
		myUtel = new MyUpdateTaskEventListener();
	}
	
	public static UpdateDatabase get() {
		if (INSTANCE == null )
			INSTANCE = new UpdateDatabase();
		return INSTANCE;
	}
	
	public static void release() {
		INSTANCE.cancelTasks();
		INSTANCE = null;
	}

	public UpdateDatabaseAdapter getUpdateDatabaseAdapter(
			IUpdateDatabaseListener udl) {
		if (uda == null) {
			uda = new UpdateDatabaseAdapter(this);
		}
		uda.setUpdateDatabaseListener(udl);
		return uda;
	}

	public boolean isRunning() {
		return isRunning;
	}

	public void setRunning(boolean isRunning) {
		this.isRunning = isRunning;
	}

	public UpdateFileTaskFacade getUpdateFile(int updateFileIndex) {
		if (updateFileIndex < 0 || updateFileIndex >= updateDatabase.size()) {
			throw new IllegalArgumentException(
					"UpdateDatabase:getUpdatefile: index out of bounds");
		}
		return updateDatabase.get(updateFileIndex);
	}

	public int getUpdateDatabaseSize() {
		return updateDatabase.size();
	}

	public int getCrrDownloadTask() {
		return crrDownloadTask;
	}

	public void setProgressListener(int updateFileIndex,
			IUpdateTaskProgressListener utpl) {
		UpdateFileTaskFacade uftf = getUpdateFile(updateFileIndex);
		uftf.getUpdateTaskProgressListener().setProgressListener(utpl);
	}

	public void setEventListener(IUpdateTaskEventListener utel) {
		this.utel = utel;
	}

	private void runTask(int updateFileIndex, boolean checkForNewer) {
		UpdateFileTaskFacade uftf = getUpdateFile(updateFileIndex);
		uftf.execute(checkForNewer);
	}

	private class MyUpdateTaskEventListener implements IUpdateTaskEventListener {

		public void notifyTaskEnded(Result res) {
//			Log.d(TAG, "MyUpdateTaskEventListener:notifyTaskEnded: crrDownloadTask = " + crrDownloadTask + " result = "
//					+ res.status);
			getUpdateFile(crrDownloadTask).clearTask();
			if (crrDownloadTask == getUpdateDatabaseSize() - 1 || res.isError() || res.isCancelled()) {
				Log.d( TAG, "MyUpdateTaskEventListener:notifyTaskEnded: terminated. result = " + res.status );
				setRunning(false);
				if ( utel != null )
					utel.notifyTaskEnded(res);
				return;
			}
			if ( utel != null ) 
				utel.notifyTaskEnded(res);

			if (crrDownloadTask < getUpdateDatabaseSize() - 1) {

				crrDownloadTask++;
				getUpdateFile(crrDownloadTask).getUpdateTaskEventListener()
						.setEventListener(this);
				runTask(crrDownloadTask, false);
			}
		}

		public void notifyNewer(Result res) {
//			Log.d(TAG, "MyUpdateTaskEventListener: notifyNewer: crrDownloadTask = " + crrDownloadTask + " result = "
//					+ res.status);
//			Log.d( TAG, "MyUpdateTaskEventListener:notifyNewer: updateDatabaseSize = " + getUpdateDatabaseSize());
			
			if (res.status == Result.STATUS_REMOTE_NEWER)
				isNewer = true;
			if (res.isError() || res.isCancelled()) {
//				Log.d(TAG, " res is error" );
				setRunning(false);
				utel.notifyTaskEnded(res);
				return;
			}

			if (crrDownloadTask < getUpdateDatabaseSize() - 1) {
				crrDownloadTask++;
				getUpdateFile(crrDownloadTask).getUpdateTaskEventListener()
						.setEventListener(this);
				runTask(crrDownloadTask, true);
			} else if (crrDownloadTask == getUpdateDatabaseSize() - 1) {
				setRunning(false);
				Result resultAgg = null;
				if (isNewer)
					resultAgg = new Result(Result.STATUS_REMOTE_NEWER,
							ErrorCode.STATUS_REMOTE_FILE_NEWER);
				else
					resultAgg = new Result(Result.STATUS_REMOTE_NOT_NEWER,
							ErrorCode.STATUS_REMOTE_FILE_NOT_NEWER);
				utel.notifyNewer(resultAgg);
			}

		}
	}

	public void runTasks(boolean checkForNewer) {
		isRunning = true;
		crrDownloadTask = 0;
		isNewer = false;
//		UpdateFileTaskFacade uftf = getUpdateFile(DE_EN_DICT);

		// Log.d( TAG, "UpdateDatabase:runTasks task started" );
		getUpdateFile(DE_EN_DICT).getUpdateTaskEventListener()
				.setEventListener(myUtel);
		runTask(DE_EN_DICT, checkForNewer);
	}

	public void cancelTasks() {
		// Log.d( TAG, "UpdateDatabase:cancelTasks" );
		isRunning = false;
		for (UpdateFileTaskFacade uft : updateDatabase) {
			uft.cancel(true);
		}
	}

}